﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using BareWeb.BuiltWithFiddler.Helper;
using Fiddler;
using Newtonsoft.Json.Linq;

namespace BareWeb.BuiltWithFiddler.Extensions
{
    public partial class BuiltWithViewer : UserControl
    {
        private string _builtWithLink = string.Empty;

        /// <summary>
        /// Initializes a new instance of the <see cref="BuiltWithViewer"/> class.
        /// </summary>
        public BuiltWithViewer()
        {
            InitializeComponent();

            this.AllowDrop = true;
            base.DragEnter += new DragEventHandler(BuiltWithViewer_DragEnter);
            base.DragDrop += new DragEventHandler(BuiltWithViewer_DragDrop);
            base.DragLeave += new EventHandler(BuiltWithViewer_DragLeave);

            pbLogo.Image = Resources.logoBig;
            pbLogo.AutoSize = false;
            //pbLogo.Width = 366;
            pbLogo.Height = 70;
            pbLogo.SizeMode = PictureBoxSizeMode.Zoom;
            pbLogo.Dock = DockStyle.Top;
        }

        /// <summary>
        /// Handles the DragLeave event of the BuiltWithViewer control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void BuiltWithViewer_DragLeave(object sender, EventArgs e)
        {
            this.BackColor = Color.FromKnownColor(KnownColor.Control);
        }

        /// <summary>
        /// Handles the DragDrop event of the BuiltWithViewer control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.DragEventArgs"/> instance containing the event data.</param>
        private void BuiltWithViewer_DragDrop(object sender, DragEventArgs e)
        {
            this.BackColor = Color.FromKnownColor(KnownColor.Control);
            tlpData.Controls.Clear();

            try
            {

                Session[] data = (Session[])e.Data.GetData("Fiddler.Session[]");
                if ((data != null) && (data.Length >= 1))
                {
                    Session dataToInspect = data[0];
                    DoBuiltWithInspect(dataToInspect);
                }
            }
            catch (Exception ex)
            {
                FiddlerApplication.Log.LogFormat("Unknown error handling Drop: {0}", ex.ToString());

                if (!CONFIG.QuietMode)
                {
                    FiddlerApplication.UI.ShowAlert(new frmAlert("Unknown Error", string.Format("An error occurred: {0}", ex.ToString()), "You may seek to retry or contact andy@bareweb.eu"));
                }
            }
        }

        /// <summary>
        /// Does the built with inspect.
        /// </summary>
        /// <param name="session">The session.</param>
        private void DoBuiltWithInspect(Session session)
        {
            var builtWithHelper = new BuiltWithHelper();
            var json = builtWithHelper.GetJsonFromBuiltWith(session.fullUrl, false);

            if (json["Error"] != null)
                throw new Exception(json["Error"].ToString());

            lblTitle.Text = Unescape(json["Title"].ToString());
            linkDomain.Text = Unescape(json["Domain"].ToString());
            linkDomain.Links.Clear();
            linkDomain.Links.Add(new LinkLabel.Link(0, linkDomain.Text.Length, session.fullUrl));
            _builtWithLink = Unescape(json["ProfileUrl"].ToString());

            tlpData.RowStyles.Clear();

            tlpData.GrowStyle = TableLayoutPanelGrowStyle.AddRows;
            tlpData.SuspendLayout();

            var orderedTechnologies = json["Technologies"].OrderBy(t => t["Tag"].Value<string>());

            var prevTag = string.Empty;
            for (int i = 0; i < orderedTechnologies.Count(); i++)
            {
                var tagText = Unescape(orderedTechnologies.ElementAt(i)["Tag"].ToString());
                if (builtWithHelper.IsExcludedTag(tagText))
                {
                    continue;
                }

                AddTableRow();

                
                if (tagText != prevTag)
                {
                    var tag = new Label()
                                  {
                                      Text = tagText
                                  };
                    tlpData.Controls.Add(tag, 0, i);

                }
                prevTag = tagText;

                var technology = Unescape(orderedTechnologies.ElementAt(i)["Name"].ToString());
                var url = Unescape(orderedTechnologies.ElementAt(i)["Link"].ToString());
                var description = Unescape(orderedTechnologies.ElementAt(i)["Description"].ToString());

                var techControl = new BuiltWithTechnologyControl(technology, url, description, 
                       string.Format("http://trends.builtwith.com/{0}/{1}", tagText, technology.Replace(" ", "-")),
                       string.Format("http://trends.builtwith.com/websitelist/{0}", technology.Replace(" ", "-")));

                tlpData.Controls.Add(techControl, 1, i);

            }
            tlpData.ResumeLayout();
        }

        /// <summary>
        /// Unescapes the specified string.
        /// </summary>
        /// <param name="s">The s.</param>
        /// <returns></returns>
        private string Unescape(string s)
        {
            return System.Text.RegularExpressions.Regex.Unescape(s).Trim('"');
        }


        /// <summary>
        /// Adds the table row.
        /// </summary>
        /// <returns></returns>
        private void AddTableRow()
        {
            tlpData.RowCount++;
            RowStyle style = new RowStyle(SizeType.AutoSize);
            tlpData.RowStyles.Add(style);
            return;
        }

        /// <summary>
        /// Handles the DragEnter event of the BuiltWithViewer control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.DragEventArgs"/> instance containing the event data.</param>
        private void BuiltWithViewer_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent("Fiddler.Session[]"))
            {
                e.Effect = DragDropEffects.Copy;
                this.BackColor = Color.LightBlue;
            }
            else
            {
                e.Effect = DragDropEffects.None;
            }
        }

        /// <summary>
        /// Handles the Click event of the btnLicencing control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void btnLicencing_Click(object sender, EventArgs e)
        {
            var helper = new BuiltWithHelper(false);

            var key = helper.GetKey();
            if (key == BuiltWithHelper.OPENLICENCEKEY)
            {
                int executedValues = FiddlerApplication.Prefs.GetInt32Pref(BuiltWithHelper.BUILTWITHFREEHITSPREF, 0);
                var result = frmPrompt.GetUserString("Licence", string.Format("The unlicenced version of BuiltWith only allows for 100 free requests per month. BuiltWith is not a free product and should not be used commercially without obtaining a licence. This Fiddler Extension offered by Bare Web integrates at their pleasure, so please consider an upgrade or contact andy@bareweb.eu for advice. You have issued {0} requests this month.", executedValues), BuiltWithHelper.OPENLICENCEKEY, true);

                if (string.IsNullOrEmpty(result))
                    return;

                if (result != string.Empty)
                {
                    helper.SetKey(result);
                }

            }
            else
            {
                var resultUpdate = frmPrompt.GetUserString("Licence", string.Format("You are currently using a licence with the key {0}. The unlicenced version of BuiltWith only allows for 100 free requests per month. BuiltWith is not a free product and should not be used commercially without obtaining a licence. This Fiddler Extension offered by Bare Web integrates at their pleasure, so please consider an upgrade or contact andy@bareweb.eu for advice. If you wish to revert to the free licence, enter FREE now. Otherwise you may enter a new key.", key), key, true);

                if (string.IsNullOrEmpty(resultUpdate))
                    return;

                if (resultUpdate.ToUpper() == "FREE")
                {
                    helper.SetKey(BuiltWithHelper.OPENLICENCEKEY);
                    FiddlerApplication.Prefs.SetInt32Pref(BuiltWithHelper.BUILTWITHFREEHITSPREF, 0);
                }
                else
                {
                    helper.SetKey(resultUpdate);
                }

            }
            FiddlerApplication.UI.ShowAlert(new frmAlert("Licence Accepted", "Please try a BuiltWith inspection to continue.", "Contact andy@bareweb.eu with any errors."));

        }

        /// <summary>
        /// Handles the LinkClicked event of the linkGeneral control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.LinkLabelLinkClickedEventArgs"/> instance containing the event data.</param>
        private void linkGeneral_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            if (e.Link.LinkData == null)
            {
                FiddlerApplication.UI.ShowAlert(new frmAlert("No site selected", "Drag a Web Session onto the BuiltWith tab to begin.", "Visit blog.bareweb.eu for more info."));
                return;
            }

            System.Diagnostics.Process.Start(e.Link.LinkData.ToString());
        }

        private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            if (_builtWithLink == string.Empty)
            {
                FiddlerApplication.UI.ShowAlert(new frmAlert("No site selected", "Drag a Web Session onto the BuiltWith tab to begin.", "Visit blog.bareweb.eu for more info."));
                return;
            }

            System.Diagnostics.Process.Start(_builtWithLink);
        }
    }
}
